local BattleReport = class("BattleReport")
local AttributeConst = require("const.AttributeConst")
local FightConst = require("const.FightConst")

function BattleReport:ctor(child)
    self.child = child or false
end

function BattleReport:addAttackSkillId(skillId)
    self.attackSkillId = skillId
end

function BattleReport:addAttackEntity(entity)
    self.attackEntity = entity:getId()
end

function BattleReport:addHurt(hurt, entity)
    if not self.hurts then
        self.hurts = {}
    end
    local hurtParam = {}
    hurtParam.value = hurt.value
    hurtParam.crit = hurt.isCrit
    hurtParam.element = hurt.element
    hurtParam.camp = entity:getCamp()
    hurtParam.entityId = entity:getId()
    hurtParam.absorb = hurt.absorb
    if hurt.resistEntityId then -- entityId替resistEntityId抵挡伤害
        hurtParam.resistId = hurt.resistEntityId
    end
    hurtParam.die = entity:isDie()
    hurtParam.blood = entity:getAttrValue(AttributeConst.BLOOD)
    hurtParam.maxBlood = entity:getAttrValue(AttributeConst.INIT_BLOOD)
    table.insert(self.hurts, hurtParam)
end

function BattleReport:newRoundBefore()
    assert(self.child == false, "can not report child by not root")
    if self.roundBefore then
        return self.roundBefore
    end
    self.roundBefore = BattleReport.new(true)
    return self.roundBefore
end

function BattleReport:newActionBefore()
    assert(self.child == false, "can not report child by not root")
    if self.actionBefore then
        return self.actionBefore
    end
    self.actionBefore = BattleReport.new(true)
    return self.actionBefore
end

function BattleReport:newAttackbefore()
    assert(self.child == false, "can not report child by not root")
    if self.attackBefore then
        return self.attackBefore
    end
    self.attackBefore = BattleReport.new(true)
    return self.attackBefore
end

function BattleReport:newAttackAfter()
    assert(self.child == false, "can not report child by not root")
    if self.attackAfter then
        return self.attackAfter
    end
    self.attackAfter = BattleReport.new(true)
    return self.attackAfter
end

function BattleReport:newActionAfter()
    assert(self.child == false, "can not report child by not root")
    if self.actionAfter then
        return self.actionAfter
    end
    self.actionAfter = BattleReport.new(true)
    return self.actionAfter
end

function BattleReport:newAttackTime(entityId)
    assert(self.child == false, "can not report child by not root")
    if not self.attackTime then
        self.attackTime = {}
    end
    if self.attackTime[entityId] then
        return self.attackTime[entityId]
    end
    self.attackTime[entityId] = BattleReport.new(true)
    return self.attackTime[entityId]
end

function BattleReport:newHurtBefore(entityId)
    assert(self.child == false, "can not report child by not root")
    if not self.hurtBefore then
        self.hurtBefore = {}
    end
    if self.hurtBefore[entityId] then
        return self.hurtBefore[entityId]
    end
    self.hurtBefore[entityId] = BattleReport.new(true)
    return self.hurtBefore[entityId]
end

function BattleReport:newHurtAfter(entityId)
    assert(self.child == false, "can not report child by not root")
    if not self.hurtAfter then
        self.hurtAfter = {}
    end
    if self.hurtAfter[entityId] then
        return self.hurtAfter[entityId]
    end
    self.hurtAfter[entityId] = BattleReport.new(true)
    return self.hurtAfter[entityId]
end

function BattleReport:setEndFlag(endFlag)
    self.endFlag = endFlag
end

function BattleReport:setRoundCount(count)
    self.roundCount = count
end

function BattleReport:addBuff(buff, entity)
    if not self.battleList then
        self.battleList = {}
    end
    local buffParam = {}
    buffParam.battleType = FightConst.BATTLE_TYPE_BUFF
    buffParam.type = buff.type
    buffParam.atrId = buff.attrId
    buffParam.id = buff.id
    buffParam.value = buff.value
    buffParam.toneup = buff.toneup
    buffParam.element = buff.element
    buffParam.camp = entity:getCamp()
    buffParam.entityId = entity:getId()
    buffParam.die = entity:isDie()
    buffParam.blood = entity:getAttrValue(AttributeConst.BLOOD)
    buffParam.maxBlood = entity:getAttrValue(AttributeConst.INIT_BLOOD)
    table.insert(self.battleList, buffParam)
end

function BattleReport:addSheild(sheild, entity)
    if not self.battleList then
        self.battleList = {}
    end
    local sheildParam = {}
    sheildParam.battleType = FightConst.BATTLE_TYPE_SHEILD
    sheildParam.id = sheild:getId()
    sheildParam.baseId = sheild:getBaseId()
    sheildParam.entityId = entity:getId()
    sheildParam.add = true
    table.insert(self.battleList, sheildParam)
end

function BattleReport:removeSheild(sheild, entity)
    if not self.battleList then
        self.battleList = {}
    end
    local sheildParam = {}
    sheildParam.battleType = FightConst.BATTLE_TYPE_SHEILD
    sheildParam.id = sheild:getId()
    sheildParam.baseId = sheild:getBaseId()
    sheildParam.entityId = entity:getId()
    sheildParam.remove = true
    table.insert(self.battleList, sheildParam)
end

function BattleReport:addEntityDie(entity)
    if not self.battleList then
        self.battleList = {}
    end
    local param = {}
    param.battleType = FightConst.BATTLE_TYPE_DIE
    param.entityId = entity:getId()
    table.insert(self.battleList, param)
end

function BattleReport:addCallObj(entity, callId)
    if not self.battleList then
        self.battleList = {}
    end
    local param = {}
    param.battleType = FightConst.BATTLE_TYPE_CALL
    param.entityId = entity:getId()
    param.camp = entity:getCamp()
    param.row = entity:getStandRow()
    param.col = entity:getStandCol()
    param.element = entity:getElement()
    param.blood = entity:getAttrValue(AttributeConst.BLOOD)
    param.maxBlood = entity:getAttrValue(AttributeConst.INIT_BLOOD)
    param.callId = callId
    table.insert(self.battleList, param)
end

function BattleReport:addSubHurt(hurt, entity, toEntity)
    if not self.battleList then
        self.battleList = {}
    end
    local suckParam = {}
    suckParam.battleType = FightConst.BATTLE_TYPE_SUBHURT
    suckParam.value = hurt.value
    suckParam.element = hurt.element
    suckParam.isCrit = hurt.isCrit
    suckParam.absorb = hurt.absorb
    suckParam.entityId = entity:getId() -- 触发者
    suckParam.toEntityId = toEntity:getId() -- 受害者
    suckParam.blood = toEntity:getAttrValue(AttributeConst.BLOOD)
    suckParam.maxBlood = toEntity:getAttrValue(AttributeConst.INIT_BLOOD)
    suckParam.die = toEntity:isDie()
    table.insert(self.battleList, suckParam)
end

function BattleReport:addFightEffect(effect, entity)
    if not self.battleList then
        self.battleList = {}
    end
    local param = {}
    param.battleType = FightConst.BATTLE_TYPE_FIGHTEFFECT
    param.id = effect:getEffectId() -- 特性id
    param.entityId = entity:getId() -- 谁作用
    table.insert(self.battleList, param)
end

function BattleReport:addHelpAttack(hurt, attack, beAttack, skillId)
    if not self.battleList then
        self.battleList = {}
    end
    local param = {}
    param.battleType = FightConst.BATTLE_TYPE_HELP
    param.skillId = skillId
    param.value = hurt.value
    param.crit = hurt.isCrit
    param.element = hurt.element
    param.absorb = hurt.absorb
    param.entityId = attack:getId()
    param.beEntityId = beAttack:getId()
    param.blood = beAttack:getAttrValue(AttributeConst.BLOOD)
    param.maxBlood = beAttack:getAttrValue(AttributeConst.INIT_BLOOD)
    param.die = beAttack:isDie()
    table.insert(self.battleList, param)
end

function BattleReport:addCounterAttack(hurt, attack, beAttack, skillId)
    if not self.battleList then
        self.battleList = {}
    end
    local param = {}
    param.battleType = FightConst.BATTLE_TYPE_COUNTER
    param.skillId = skillId
    param.value = hurt.value
    param.crit = hurt.isCrit
    param.element = hurt.element
    param.absorb = hurt.absorb
    param.entityId = attack:getId()
    param.beEntityId = beAttack:getId()
    param.blood = beAttack:getAttrValue(AttributeConst.BLOOD)
    param.maxBlood = beAttack:getAttrValue(AttributeConst.INIT_BLOOD)
    param.die = beAttack:isDie()
    table.insert(self.battleList, param)
end

function BattleReport:convertToTable()
    local convertParam = {
        ["attackSkillId"] = {},
        ["attackEntity"] = {},
        ["roundCount"] = {},
        ["endFlag"] = {},
        ["hurts"] = {},
        ["roundBefore"] = {buff = true},
        ["actionBefore"] = {buff = true},
        ["actionAfter"] = {buff = true},
        ["attackBefore"] = {buff = true},
        ["attackTime"] = {buff = true},
        ["attackAfter"] = {buff = true},
        ["hurtBefore"] = {buff = true},
        ["hurtAfter"] = {buff = true},
        ["counterAttack"] = {counter = true}
    }
    local convertBuff = function(data, battleData)
        if not battleData then
            return
        end
        data.reportBuffs = battleData.reportBuffs
        data.reportSheilds = battleData.reportSheilds
        data.dieEntitys = battleData.dieEntitys
        data.callObjs = battleData.callObjs
        data.reportSubHurt = battleData.reportSubHurt
        data.reportFightEffects = battleData.reportFightEffects
    end
    local battle = {}
    for name, data in pairs(convertParam) do
        if data.buff then
            battle[name] = {}
            convertBuff(battle[name], self[name])
        elseif data.counter then
            battle[name] = self[name]:convertToTable()
        else
            battle[name] = self[name]
        end
    end
    return battle
end

return BattleReport
